package com.jwsoft.manager.core.dao.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.jwsoft.manager.common.enums.DataSaveEnum;
import com.jwsoft.manager.common.vo.eduAddressTree.AddressBoundCheckVO;
import com.jwsoft.manager.common.vo.eduAddressTree.AddressTreeVO;
import com.jwsoft.manager.common.vo.eduAddressTree.EduAddressTreeVO;
import com.jwsoft.manager.core.dao.model.EduAddress;
import com.jwsoft.manager.core.dao.model.EduAddressTree;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

/**
 * 服务类
 *
 * @author fangs
 * @since 2023-02-03
 */
public interface EduAddressTreeService extends IService<EduAddressTree> {
    /**
     * 节点移动：移动节点
     *
     * @param moveNode 需要移动的节点
     * @param target   移动节点到该节点下
     */
    void moveTreeNode(AddressTreeVO moveNode, AddressTreeVO target);

    /**
     * 获取地址链
     *
     * @param leafId 叶子节点id
     * @return 地址链
     * @author fangs
     */
    List<AddressTreeVO> getAddressChain(Long leafId);

    /**
     * 保存新节点,如果新节点的上级节点是末级，则将上级节点修改为非末级节点
     *
     * @param eduAddressTree 节点实体
     * @author fangs
     */
    void saveNewNode(EduAddressTree eduAddressTree);

    /**
     * 节点合并，将2个节点合并为一个节点
     *
     * @param majorNode 合并主节点
     * @param slaveNode 合并从节点
     * @return 合并后的节点
     * @author fangs
     */
    AddressTreeVO mergeNode(AddressTreeVO majorNode, AddressTreeVO slaveNode);

    /**
     * 节点合并,将多个节点合并到主节点
     *
     * @param list        需要合并的节点
     * @param masterIndex 主节点位置
     * @return 合并后的节点
     * @author fangs
     */
    AddressTreeVO mergeNode(List<AddressTreeVO> list, Integer masterIndex);

    /**
     * 节点合并,将多个节点合并到主节点
     *
     * @param list        需要合并的节点
     * @param masterIndex 主节点位置
     * @param isOneStreet 是否是同一条街道
     * @return 合并后的节点
     * @author fangs
     */
    AddressTreeVO mergeNode(List<AddressTreeVO> list, Integer masterIndex, Boolean isOneStreet);

    /**
     * 从多个节点名字中抽取共同字段为新的父节点
     * 如：
     * -：                  江镇：
     * 江镇锦源村             锦源村
     * 江镇东门村   ------>   东门村
     * 江镇枫树头村           枫树头村
     *
     * @param list 节点集合
     * @return 抽取后的共同节点
     * @author fangs
     */
    AddressTreeVO mergeNodeAndCreateParent(List<AddressTreeVO> list);

    /**
     * 应用合并更改
     *
     * @param saveData 更改元数据
     * @param idMap    id替换存储容器，用于存储虚拟id和真是id的映射关系
     * @author fangs
     */
    void applyMerge(Map<DataSaveEnum, List<EduAddressTreeVO>> saveData, Map<Long, Long> idMap);

    /**
     * 根据id找到子节点
     *
     * @param addressId 节点id
     * @return 子节点
     */
    List<EduAddressTree> getChildrenById(Long addressId);

    /**
     * 得到节点的链路信息  截止到 district 以下
     *
     * @param treeId 节点id
     * @return 链路信息（包含该节点的所有父级节点）
     */
    List<EduAddressTree> getLinkByTreeId(Long treeId);


    /**
     * 变动节点下移,将当前节点的change标记修改为0，将其所有子节点的change标记修改为1
     *
     * @param eduAddressTree 当前节点
     * @author fangs
     */
    void changeDown(EduAddressTree eduAddressTree);

    /**
     * 判断传入的节点集合是否是同一街道
     *
     * @param list 节点集合
     * @return 是否是同一街道
     * @author fangs
     */
    Boolean isOneStreet(List<AddressTreeVO> list);

    /**
     * 根据行政区划，得到树节点信息
     * @param provinceCode
     * @return
     */
    EduAddressTree getAddressByAreaCode(String provinceCode);

    /**
     * 筛选出的绑定节点数据，需要考虑绑定情况
     * @param areaType
     * @param mixNum
     * @param parentId
     * @param schoolId
     * @return
     */
    List<AddressBoundCheckVO> queryBoundLessAsLeafNodes(String areaType,
                                                        Integer mixNum,
                                                        Long parentId,
                                                        String schoolId);

    /**
     * 筛选出的绑定节点数据，不需要考虑绑定情况
     * @param treeId
     * @param schoolId
     * @return
     */
    List<AddressBoundCheckVO> queryBoundLeafNode(Long treeId, String schoolId);

    /**
     * 根据树节点链路信息进行删除
     * @param treeNodes 树节点链路
     */
    void removeByTreeLink(List<EduAddressTree> treeNodes);

    /**
     * 根据当前id，获取所有子级节点数据
     * @param treeId
     * @return
     */
    List<EduAddressTree> getAllDescendants(Long treeId);

    /**
     * 根据树id，得到地址节点数据
     * @param treeIds
     * @return
     */
    List<EduAddress> getAddressByTreeId(List<Long> treeIds);
}
